package cn.lili.modules.payment.serviceimpl;

import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.AuthUser;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.security.enums.SceneEnums;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.common.utils.ResultUtil;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.constant.CommonConstant;
import cn.lili.modules.kit.params.WithdrawParams;
import cn.lili.modules.payment.entity.dos.LiUserPointsWithdraw;
import cn.lili.modules.payment.entity.dos.UserPointsHistory;
import cn.lili.modules.payment.entity.dos.UserWallet;
import cn.lili.modules.payment.mapper.LiUserPointsHistoryMapper;
import cn.lili.modules.payment.service.LiUserPointsHistoryService;
import cn.lili.modules.payment.service.LiUserPointsWithdrawService;
import cn.lili.modules.wallet.service.WalletService;
import cn.lili.mybatis.util.PageUtil;
import com.api.PayApi;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author asus
 * @description 针对表【li_user_points_history(会员积分记录表)】的数据库操作Service实现
 * @createDate 2023-10-09 16:03:04
 */
@Service
public class LiUserPointsHistoryServiceImpl extends ServiceImpl<LiUserPointsHistoryMapper, UserPointsHistory>
        implements LiUserPointsHistoryService {

    @Autowired
    private PayApi payApi;

    @Autowired
    private LiUserPointsWithdrawService pointsWithdrawService;

    @Autowired
    private WalletService walletService;

    @Override
    public ResultMessage<Page<UserPointsHistory>> pointsPage(WithdrawParams withdrawParams) {
        AuthUser currentUser = UserContext.getCurrentUser();
        if (currentUser == null) {
            return ResultUtil.error(500, "登录已过期");
        }
        LambdaQueryWrapper<UserPointsHistory> historyLambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotEmpty(withdrawParams.getUserId())) {
            historyLambdaQueryWrapper.eq(UserPointsHistory::getMemberId, withdrawParams.getUserId());
        } else {
            if (SceneEnums.URBAN_SUBSTATION.equals(UserContext.getCurrentUser().getScene())) {
                historyLambdaQueryWrapper.eq(UserPointsHistory::getMemberId, currentUser.getId());
            }else {
                historyLambdaQueryWrapper.eq(UserPointsHistory::getMemberId, currentUser.getExtendId());
            }

        }
        historyLambdaQueryWrapper.orderByDesc(UserPointsHistory::getCreateTime);
        Page<UserPointsHistory> pointsHistoryPage = this.page(PageUtil.initPage(withdrawParams), historyLambdaQueryWrapper);
        return ResultUtil.data(pointsHistoryPage);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultMessage<Object> withdraw(WithdrawParams withdrawParams) {
        AuthUser currentUser = UserContext.getCurrentUser();
        this.check(withdrawParams, currentUser);
        Map<String, String> userMap = this.sceneSet(currentUser);
        String uid = StringUtils.isNotEmpty(withdrawParams.getUserId()) ? withdrawParams.getUserId() : String.valueOf(userMap.get("id"));

        //添加提现记录
//        UserWallet userWallet = walletService.getOne(new LambdaQueryWrapper<UserWallet>().eq(UserWallet::getUserId, uid).last("limit 1"));
        UserWallet userWallet = walletService.getFromUserid(uid);
        if (userWallet == null) {
            return ResultUtil.error(500, "未找到用户钱包");
        }
        if (userWallet.getPoints() < Double.parseDouble(withdrawParams.getMoney())) {
            return ResultUtil.error(500, "积分余额不够。当前积分余额:" + userWallet.getPoints() + ",提现积分:" + withdrawParams.getMoney());
        }
        String remark = currentUser.getNickName() + "提现:" + withdrawParams.getMoney();
        LiUserPointsWithdraw pointsWithdraw = new LiUserPointsWithdraw();
        pointsWithdraw.setCreateBy(uid);
        pointsWithdraw.setCreateTime(new Date());
        pointsWithdraw.setMemberId(userMap.get("id") != null? Long.valueOf(userMap.get("id")) : null);
        pointsWithdraw.setMemberName(userMap.get("name") != null? String.valueOf(userMap.get("name")) : null);
        pointsWithdraw.setRemark(remark);
        pointsWithdraw.setBeforePoint(String.valueOf(userWallet.getPoints()));
        pointsWithdraw.setMoney(String.valueOf(withdrawParams.getMoney()));
        pointsWithdraw.setAfterPoint(String.valueOf(CurrencyUtil.sub(userWallet.getPoints(), Integer.parseInt(withdrawParams.getMoney()))));
        pointsWithdraw.setWithdrawType(CommonConstant.WITHDRAW_TYPE_1);
        pointsWithdrawService.save(pointsWithdraw);

        //添加绿色积分变动日志
        this.savePoints(withdrawParams, uid, currentUser, userWallet);

        //变更钱包的余额
        userWallet.setPoints(Double.valueOf(pointsWithdraw.getAfterPoint()));
        walletService.updateById(userWallet);

        //提现
        boolean payment = payApi.gMoneyPayment(currentUser.getOpenId(), remark, 0, Integer.parseInt(withdrawParams.getMoney()), 2, 3);
        if (!payment) {
            throw new ServiceException("服务异常，用户提现失败");
        }
        return ResultUtil.data(payment);
    }

    public void check(WithdrawParams withdrawParams, AuthUser currentUser) {
        if (!StringUtils.isNumeric(withdrawParams.getMoney())) {
            throw new ServiceException("提现金额请输入数字");
        }
        if (withdrawParams.getMoney() == null) {
            throw new ServiceException("提现金额为空");
        }
        if (!isLong(withdrawParams.getMoney())) {
            throw new ServiceException("提现积分单位为分，不存在小数，请输入正整数。");
        }
        if (currentUser == null) {
            throw new ServiceException("登录已过期");
        }
        if (StringUtils.isEmpty(currentUser.getOpenId())) {
            throw new ServiceException("当前用户未绑定飞语");
        }
    }

    @Override
    public void savePoints(WithdrawParams withdrawParams, String uid, AuthUser currentUser, UserWallet userWallet) {
        UserPointsHistory userPointsHistory = new UserPointsHistory();
        userPointsHistory.setCreateBy(currentUser.getId());
        userPointsHistory.setCreateTime(new Date());
        userPointsHistory.setPoints(CurrencyUtil.sub(userWallet.getPoints(), Double.parseDouble(withdrawParams.getMoney())));
        userPointsHistory.setPointType("withdraw");
        userPointsHistory.setBeforePoint(userWallet.getPoints());
        userPointsHistory.setVariablePoint(Double.valueOf(withdrawParams.getMoney()));
        Map<String, String> userMap = this.sceneSet(currentUser);
        userPointsHistory.setMemberId(userMap.get("id") != null? String.valueOf(userMap.get("id")) : null);
        userPointsHistory.setMemberName(userMap.get("name") != null? String.valueOf(userMap.get("name")) : null);
        super.save(userPointsHistory);
    }

    /**
     * 是否为整形数据
     * @param val 数据
     * @return 是否为整形数据
     */
    public Boolean isLong(String val) {
        try {
            Long.valueOf(val);
            return true;
        } catch (Exception e) {
            return false;
        }
    }


    /**
     * 不同场景设置不同的用户属性
     */
    public Map<String, String> sceneSet(AuthUser currentUser) {
        Map<String, String> map = new HashMap<>();
        switch (currentUser.getScene()) {
            case MEMBER -> {
                map.put("id", currentUser.getId());
                map.put("name", currentUser.getNickName());
                break;
            }
            case STORE, SUPPLIER, URBAN_SUBSTATION -> {
                map.put("id", currentUser.getExtendId());
                map.put("name", currentUser.getExtendName());
                break;
            }
            default -> {
                map.put("id", currentUser.getId());
                map.put("name", currentUser.getNickName());
            }
        }
        return map;
    }
}




